#include "WmarkDev.h"

namespace camera
{
    namespace algorithm
    {
        WmarkDev *WmarkDev::instance = NULL;
        WmarkDev::WmarkDev() : Device(DEV, O_RDONLY)
        {
        }
        WmarkDev::~WmarkDev()
        {
        }

        int WmarkDev::getWmarkBufsInfo(uint32_t &bufNum, uint64_t &bufLen)
        {
            int ret = -1;
            init_wmark_bufs_t msg;

            ret = ioctlDev(GET_INIT_WMARK_BUFS, &msg);
            if (ret)
            {
                ALOGE("%s %d error", __func__, __LINE__);
                return ret;
            }

            bufNum = msg.num;
            bufLen = msg.len;

            return ret;
        }

        bool WmarkDev::threadLoop()
        {
            handlePoll();
            return true;
        }

        void WmarkDev::start()
        {
            this->run("client-lib-wmarkdev-thread", android::PRIORITY_HIGHEST);
        }

        void WmarkDev::stop()
        {
            requestExitAndWait();
        }

        int WmarkDev::handlePoll()
        {
            struct epoll_event ev, events[MAX_EVENTS];
            int listen_sock, conn_sock, nfds, epollfd;
            uint32_t flag = EPOLLIN | EPOLLMSG;
            int wmark_dev_fd = getFd();
            int n = 0;

            epollfd = epoll_create1(0);
            if (epollfd == -1)
            {
                perror("epoll_create1");
                ALOGE("%s %d error: epoll_create1 %s", __func__, __LINE__, strerror(errno));
                return -1;
            }

            ev.events = flag;
            ev.data.fd = wmark_dev_fd;
            if (epoll_ctl(epollfd, EPOLL_CTL_ADD, wmark_dev_fd, &ev) == -1)
            {
                perror("epoll_ctl:");
                ALOGE("%s %d error: epoll_ctl %s", __func__, __LINE__, strerror(errno));
                return -1;
            }

            for (;;)
            {
                nfds = epoll_wait(epollfd, events, MAX_EVENTS, -1);
                if (nfds == -1)
                {
                    perror("epoll_wait");
                    ALOGE("%s %d error: epoll_wait %s", __func__, __LINE__, strerror(errno));
                    return -1;
                }

                for (n = 0; n < nfds; ++n)
                {
                    if (events[n].data.fd == wmark_dev_fd)
                    {
                        if (events[n].events & EPOLLIN) {
                            ALOGD("event -> EPOLLIN");
                            getUseWBufInfo();
                        } else if (events[n].events & EPOLLMSG) {
                            ALOGD("event -> EPOLLMSG");
                            getMsgCtl();
                        }

                    }
                    else
                    {
                        ALOGE("%s %d error.\n", __func__, __LINE__);
                    }
                }
            }
            return 0;
        }

        int WmarkDev::getUseWBufInfo()
        {
            int ret = -1;
            wmark_buf_t msg;

            ret = ioctlDev(GET_USE_BUF_INDEX_IMPORT, &msg);
            if (ret)
            {
                ALOGE("%s %d error", __func__, __LINE__);
                return ret;
            }

            if (mResultCallBack) {
                mResultCallBack->onResult(msg);
            }

            return ret;
        }

        int WmarkDev::setFreeWBufInfo(int dmaBufIndex)
        {
            int ret = -1;
            wmark_buf_t msg;

            if (dmaBufIndex > DMA_BUFS_MAX_NUM || dmaBufIndex < 0) {
                ALOGE("%s %d dmabufIndex error", __func__, __LINE__);
                return -1;
            }

            msg.index = dmaBufIndex;

            ret = ioctlDev(SET_FREE_BUF_INDEX_IMPORT, &msg);
            if (ret)
            {
                ALOGE("%s %d error", __func__, __LINE__);
                return ret;
            }

            return ret;
        }

        int WmarkDev::getMsgCtl()
        {
            int ret = -1;
            control_msg_t msg;

            ret = ioctlDev(GET_MSG_CTL, &msg);
            if (ret)
            {
                ALOGE("%s %d error", __func__, __LINE__);
                return ret;
            }

            ALOGD("%s %d : sm=%d ", __func__, __LINE__, msg.state);

            if (mCtlMsgCallBack) {
                mCtlMsgCallBack->onResult(msg);
            }

            return ret;
        }

    } // algorithm
} // camera
